package com.bdilab.iot.service.impl;

import com.bdilab.iot.dao.*;
import com.bdilab.iot.dto.userdto.CreateUserDto;
import com.bdilab.iot.dto.userdto.LoginResultDto;
import com.bdilab.iot.dto.userdto.UpdateUserDto;
import com.bdilab.iot.dto.userdto.UserDetail;
import com.bdilab.iot.exception.NotFoundException;
import com.bdilab.iot.exception.ServerException;
import com.bdilab.iot.model.*;
import com.bdilab.iot.service.UserService;
import com.bdilab.iot.utils.ParsePermissionUtils;
import io.jsonwebtoken.lang.Collections;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author WangNing
 * @version 1.0
 * @date 2020/7/31 19:07
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Resource
    ProjectMapper projectMapper;

    @Resource
    UserRoleRelationMapper roleRelationMapper;

    @Resource
    PermissionMapper permissionMapper;

    @Resource
    UserMapper userMapper;

    @Resource
    RoleMapper roleMapper;

    @Autowired
    PasswordEncoder passwordEncoder;



    @Override
    public User getUserByUserName(String userName) {

        return userMapper.selectByUserName(userName);
    }

    /**
     * 创建角色
     * @param createUserDto
     * @return
     */
    @Override
    @Transactional
    public synchronized LoginResultDto createUser(CreateUserDto createUserDto) {
        int count = userMapper.countByUsername(createUserDto.getName());
        if(count >=0)
            throw new ServerException("该用户名已存在");
        if(Collections.isEmpty(createUserDto.getRoles())){
            throw new ServerException("用户必须至少指定一个角色");
        }

        List<Long> roleIds = roleMapper.getAllRoleId();

        if(createUserDto.getRoles().stream().distinct().count()>0)
            throw new ServerException("用户绑定重复的角色");

        createUserDto.getRoles().forEach(r->{

            if(!roleIds.contains(r))
                throw new ServerException("用户绑定系统不存在的角色");

        });
        Project project = projectMapper.selectById(createUserDto.getProject());
        if(project == null)
            throw new ServerException("用户绑定的项目不存在");

        User user = new User();
        user.setActive(true);
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        user.setProject(project.getId());
        user.setLevel(project.getProjectClass());
        user.setPassword(passwordEncoder.encode(createUserDto.getPassword()));
        user.setPhoneNum(createUserDto.getPhoneNum());

        int result = userMapper.insert(user);
        if(result <=0 ){
            log.error("生成新用户出现未知错误:{}",createUserDto.getName());
            throw new ServerException("生成新用户出现未知错误");
        }
        List<UserRoleRelation> userRoleRelations = new ArrayList<>();
        createUserDto.getRoles().forEach(r->{
            UserRoleRelation roleRelation = new UserRoleRelation();
            roleRelation.setUserId(user.getId());
            roleRelation.setRoleId(r);
            userRoleRelations.add(roleRelation);
        });
        result = roleRelationMapper.insertBatch(userRoleRelations);
        if(result < 0){

            log.error("用户绑定角色时出现未知错误:{}",createUserDto.getName());
            throw new ServerException("用户绑定角色时出现未知错误");

        }
        LoginResultDto loginResultDto = new LoginResultDto();
        BeanUtils.copyProperties(user, loginResultDto);
        return loginResultDto;

    }

    @Override
    @Transactional
    public void updateUser(UpdateUserDto updateUserDto, Long userId) {

        User user = new User();
        user.setId(userId);
        user.setUpdateTime(new Date());

        if(updateUserDto.getProject()!=null){
            Project project = projectMapper.selectById(updateUserDto.getProject());
            if(project == null)
                throw new ServerException("用户绑定的项目不存在");
            user.setProject(project.getId());
        }
        if(updateUserDto.getActive()!=null){
            user.setActive(updateUserDto.getActive());
        }
        user.setPhoneNum(updateUserDto.getPhoneNum());
        if(updateUserDto.getRoles()!=null){

            if(updateUserDto.getRoles().size() ==0){
                throw new ServerException("用户必须至少指定一个角色");
            }
            List<Long> roleIds = roleMapper.getAllRoleId();

            if(updateUserDto.getRoles().stream().distinct().count()>0)
                throw new ServerException("用户绑定重复的角色");

            updateUserDto.getRoles().forEach(r->{

                if(!roleIds.contains(r))
                    throw new ServerException("用户绑定系统不存在的角色");

            });

            int result = roleRelationMapper.deleteByUserId(userId);
            if(result < 0)
                throw new ServerException("重置用户角色出现错误");

            List<UserRoleRelation> userRoleRelations = new ArrayList<>();
            updateUserDto.getRoles().forEach(r->{
                UserRoleRelation roleRelation = new UserRoleRelation();
                roleRelation.setUserId(user.getId());
                roleRelation.setRoleId(r);
                userRoleRelations.add(roleRelation);
            });
            result = roleRelationMapper.insertBatch(userRoleRelations);
            if(result < 0){

                log.error("用户绑定角色时出现未知错误:{}",userId);
                throw new ServerException("用户绑定角色时出现未知错误");

            }

        }

        int result = userMapper.updateUser(user);
        if(result < 0){
            log.error("更新用户出现未知错误:{}", userId);
            throw new ServerException("更新用户出现未知错误");
        }

    }

    @Override
    @Transactional
    public void deleteUser(Long userId) {
        if(userId <= 1)
            throw new ServerException("无效的用户ID");
        int result = userMapper.deleteById(userId);
        if(result <=0)
            throw new NotFoundException("用户不存在");
        result = roleRelationMapper.deleteByUserId(userId);
        if(result < 0)
            throw new ServerException("清空用户角色出现未知错误");
    }

    @Override
    public UserDetail getMyUserDetail(User user) {

        UserDetail userDetail = new UserDetail();

        List<Role> roles = roleRelationMapper.getRolesByUserId(user.getId());
        List<Long> roleIds = roles.stream().filter(Objects::nonNull).map(Role::getId).collect(Collectors.toList());
        List<Permission> permissions;
        if(user.getId() ==1 && user.getUsername().equals("admin")){

            // 超级管理员 释放全部权限
            userDetail.setAdmin(true);
            permissions = permissionMapper.getAllPermission();
            roles.clear();
            Role role = new Role();
            role.setId(-1L);
            role.setName("超级管理员");
            role.setDescription("系统管理员");
            role.setUpdateTime(new Date());
            role.setCreateTime(new Date());
            roles.add(role);

        }else {
            permissions = permissionMapper.selectByRoles(roleIds);
        }

        Map<String, Map<String, List<Permission>>> permissionMap = ParsePermissionUtils.parsePermission(permissions);

        BeanUtils.copyProperties(user, userDetail, "password");
        userDetail.setRoles(roles);
        userDetail.setPermissions(permissionMap);

        return userDetail;

    }

    @Override
    public UserDetail getUserDetailByUserId(Long userId) {
        User user = userMapper.selectById(userId);
        if(user == null)
            throw new NotFoundException("系统不存在该用户");
        return getMyUserDetail(user);
    }
}
